#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED

#include "Vector3.h"

class Matrix3x3
{
private:
    Vector3 a;
    Vector3 b;
    Vector3 c;
public:
    Matrix3x3();
    Matrix3x3(double New_x1, double New_y1, double New_z1, double New_x2, double New_y2, double New_z2, double New_x3, double New_y3, double New_z3)
    {
        a.set(New_x1, New_y1, New_z1);
        b.set(New_x2, New_y2, New_z2);
        c.set(New_x3, New_y3, New_z3);
    }

    //Matrix3x3(double *New_x1, double *New_y1, double *New_z1, double *New_x2, double *New_y2, double *New_z2, double *New_x3, double *New_y3, double *New_z3);
    Matrix3x3(Vector3 V1, Vector3 V2, Vector3 V3)
    {
        a = V1;
        b = V2;
        c = V3;
    }

    /*Matrix3x3(Vector3 *V1, Vector3 V2, Vector3 V3);
    Matrix3x3(Vector3 V1, Vector3 *V2, Vector3 V3);
    Matrix3x3(Vector3 V1, Vector3 V2, Vector3 *V3);
    Matrix3x3(Vector3 V1, Vector3 *V2, Vector3 *V3);
    Matrix3x3(Vector3 *V1, Vector3 V2, Vector3 *V3);
    Matrix3x3(Vector3 *V1, Vector3 *V2, Vector3 V3);
    Matrix3x3(Vector3 *V1, Vector3 *V2, Vector3 *V3);*/
    Matrix3x3(const Matrix3x3 &M)
    {
        a = M.getA();
        b = M.getB();
        c = M.getC();
    }

    /*Matrix3x3(Vector3 New_A, Vector3 New_B, double New_Cx, double New_Cy, double New_Cz);
    Matrix3x3(Vector3 *New_A, Vector3 New_B, double New_Cx, double New_Cy, double New_Cz);
    Matrix3x3(Vector3 New_A, Vector3 *New_B, double New_Cx, double New_Cy, double New_Cz);
    Matrix3x3(Vector3 *New_A, Vector3 *New_B, double New_Cx, double New_Cy, double New_Cz);
    Matrix3x3(Vector3 New_A,  double New_Bx, double New_By, double New_Bz, Vector3 New_C);
    Matrix3x3(Vector3 *New_A,  double New_Bx, double New_By, double New_Bz, Vector3 New_C);
    Matrix3x3(Vector3 New_A,  double New_Bx, double New_By, double New_Bz, Vector3 *New_C);
    Matrix3x3(Vector3 *New_A,  double New_Bx, double New_By, double New_Bz, Vector3 *New_C);
    Matrix3x3(double New_Ax, double New_Ay, double New_Az, Vector3 New_B, Vector3 New_C);
    Matrix3x3(double New_Ax, double New_Ay, double New_Az, Vector3 *New_B, Vector3 New_C);
    Matrix3x3(double New_Ax, double New_Ay, double New_Az, Vector3 New_B, Vector3 *New_C);
    Matrix3x3(double New_Ax, double New_Ay, double New_Az, Vector3 *New_B, Vector3 *New_C);
    Matrix3x3(Vector3 New_A, double New_Bx, double New_By, double New_Bz, double New_Cx, double New_Cy, double New_Cz);
    Matrix3x3(Vector3 *New_A, double New_Bx, double New_By, double New_Bz, double New_Cx, double New_Cy, double New_Cz);
    Matrix3x3(double New_Ax, double New_Ay, double New_Az, Vector3 New_B, double New_Cx, double New_Cy, double New_Cz);
    Matrix3x3(double New_Ax, double New_Ay, double New_Az, Vector3 *New_B, double New_Cx, double New_Cy, double New_Cz);
    Matrix3x3(double New_Ax, double New_Ay, double New_Az, double New_Bx, double New_By, double New_Bz, Vector3 New_C);
    Matrix3x3(double New_Ax, double New_Ay, double New_Az, double New_Bx, double New_By, double New_Bz, Vector3 *New_C);*/



    void set(double New_x1, double New_y1, double New_z1, double New_x2, double New_y2, double New_z2, double New_x3, double New_y3, double New_z3)
    {
        a.set(New_x1, New_y1, New_z1);
        b.set(New_x2, New_y2, New_z2);
        c.set(New_x3, New_y3, New_z3);
    }
    //Matrix3x3 set(double *New_x1, double *New_y1, double *New_z1, double *New_x2, double *New_y2, double *New_z2, double *New_x3, double *New_y3, double *New_z3);
    void set(Vector3 V1, Vector3 V2, Vector3 V3)
    {
        a = V1;
        b = V2;
        c = V3;
    }
    /*Matrix3x3 set(Vector3 *V1, Vector3 V2, Vector3 V3);
    Matrix3x3 set(Vector3 V1, Vector3 *V2, Vector3 V3);
    Matrix3x3 set(Vector3 V1, Vector3 V2, Vector3 *V3);
    Matrix3x3 set(Vector3 V1, Vector3 *V2, Vector3 *V3);
    Matrix3x3 set(Vector3 *V1, Vector3 V2, Vector3 *V3);
    Matrix3x3 set(Vector3 *V1, Vector3 *V2, Vector3 V3);
    Matrix3x3 set(Vector3 *V1, Vector3 *V2, Vector3 *V3);*/
    /*Matrix3x3 set(Vector3 New_POS, Vector3 New_DIR, double New_UPx, double New_UPy, double New_UPz);
    //Matrix3x3 set(Vector3 *New_POS, Vector3 New_DIR, double New_UPx, double New_UPy, double New_UPz);
    //Matrix3x3 set(Vector3 New_POS, Vector3 *New_DIR, double New_UPx, double New_UPy, double New_UPz);
    //Matrix3x3 set(Vector3 *New_POS, Vector3 *New_DIR, double New_UPx, double New_UPy, double New_UPz);
    Matrix3x3 set(Vector3 New_POS,  double New_DIRx, double New_DIRy, double New_DIRz, Vector3 New_UP);
    //Matrix3x3 set(Vector3 *New_POS,  double New_DIRx, double New_DIRy, double New_DIRz, Vector3 New_UP);
    //Matrix3x3 set(Vector3 New_POS,  double New_DIRx, double New_DIRy, double New_DIRz, Vector3 *New_UP);
    //Matrix3x3 set(Vector3 *New_POS,  double New_DIRx, double New_DIRy, double New_DIRz, Vector3 *New_UP);
    Matrix3x3 set(double New_POSx, double New_POSy, double New_POSz, Vector3 New_DIR, Vector3 New_UP);
    //Matrix3x3 set(double New_POSx, double New_POSy, double New_POSz, Vector3 *New_DIR, Vector3 New_UP);
    //Matrix3x3 set(double New_POSx, double New_POSy, double New_POSz, Vector3 New_DIR, Vector3 *New_UP);
    //Matrix3x3 set(double New_POSx, double New_POSy, double New_POSz, Vector3 *New_DIR, Vector3 *New_UP);
    Matrix3x3 set(Vector3 New_POS, double New_DIRx, double New_DIRy, double New_DIRz, double New_UPx, double New_UPy, double New_UPz);
    //Matrix3x3 set(Vector3 *New_POS, double New_DIRx, double New_DIRy, double New_DIRz, double New_UPx, double New_UPy, double New_UPz);
    Matrix3x3 set(double New_POSx, double New_POSy, double New_POSz, Vector3 New_DIR, double New_UPx, double New_UPy, double New_UPz);
    //Matrix3x3 set(double New_POSx, double New_POSy, double New_POSz, Vector3 *New_DIR, double New_UPx, double New_UPy, double New_UPz);
    Matrix3x3 set(double New_POSx, double New_POSy, double New_POSz, double New_DIRx, double New_DIRy, double New_DIRz, Vector3 New_UP);
    //Matrix3x3 set(double New_POSx, double New_POSy, double New_POSz, double New_DIRx, double New_DIRy, double New_DIRz, Vector3 *New_UP);*/


    void setA(Vector3 New_A)  {a = New_A;}
    //Matrix3x3 setA(Vector3 *New_A) {a = *New_A; return *this;}
    void setA(double x, double y, double z) {a.set(x,y,z);}
    /*void setA(double *x, double y, double z) {a.set(*x,y,z);}
    void setA(double x, double *y, double z) {a.set(x,*y,z);}
    void setA(double x, double y, double *z) {a.set(x,y,*z);}
    void setA(double *x, double *y, double z) {a.set(*x,*y,z);}
    void setA(double *x, double y, double *z) {a.set(*x,y,*z);}
    void setA(double x, double *y, double *z) {a.set(x,*y,*z);}
    void setA(double *x, double *y, double *z) {a.set(*x,*y,*z);}*/


    void setB(Vector3 New_B)  {b = New_B;}
    //Matrix3x3 setB(Vector3 *New_B) {b = *New_B; return *this;}
    void setB(double x, double y, double z) {b.set(x,y,z);}
    /*void setB(double *x, double y, double z) {b.set(*x,y,z);}
    void setB(double x, double *y, double z) {b.set(x,*y,z);}
    void setB(double x, double y, double *z) {b.set(x,y,*z);}
    void setB(double *x, double *y, double z) {b.set(*x,*y,z);}
    void setB(double *x, double y, double *z) {b.set(*x,y,*z);}
    void setB(double x, double *y, double *z) {b.set(x,*y,*z);}
    void setB(double *x, double *y, double *z) {b.set(*x,*y,*z);}*/

    void setC(Vector3 New_C)  {c = New_C;}
    //Matrix3x3 setC(Vector3 *New_C) {c = *New_C; return *this;}
    void setC(double x, double y, double z) {c.set(x,y,z);}
    /*void setC(double *x, double y, double z) {c.set(*x,y,z);}
    void setC(double x, double *y, double z) {c.set(x,*y,z);}
    void setC(double x, double y, double *z) {c.set(x,y,*z);}
    void setC(double *x, double *y, double z) {c.set(*x,*y,z);}
    void setC(double *x, double y, double *z) {c.set(*x,y,*z);}
    void setC(double x, double *y, double *z) {c.set(x,*y,*z);}
    void setC(double *x, double *y, double *z) {c.set(*x,*y,*z);}*/


    Vector3 getA() const {return a;}
    double getAX() const {return a.getX();}
    double getAY() const {return a.getY();}
    double getAZ() const {return a.getZ();}

    Vector3 getB() const {return b;}
    double getBX() const {return b.getX();}
    double getBY() const {return b.getY();}
    double getBZ() const {return b.getZ();}

    Vector3 getC() const {return c;}
    double getCX() const {return c.getX();}
    double getCY() const {return c.getY();}
    double getCZ() const {return c.getZ();}


    Matrix3x3 operator = (Matrix3x3 M);
    //Matrix3x3 operator = (Matrix3x3 *M);
    Matrix3x3 operator += (Matrix3x3 M);
    //Matrix3x3 operator += (Matrix3x3 *M);
    Matrix3x3 operator -= (Matrix3x3 M);
    //Matrix3x3 operator -= (Matrix3x3 *M);
    Matrix3x3 operator *= (Matrix3x3 M);
    //Matrix3x3 operator *= (Matrix3x3 *M);
    Matrix3x3 operator *= (double R);
    //Matrix3x3 operator *= (double *R);
    Matrix3x3 operator /= (double R);
    //Matrix3x3 operator /= (double *R);
    Matrix3x3 operator + (Matrix3x3 M);
    //Matrix3x3 operator + (Matrix3x3 *M);
    Matrix3x3 operator - (Matrix3x3 M);
    //Matrix3x3 operator - (Matrix3x3 *M);
    Matrix3x3 operator * (Matrix3x3 M);
    //Matrix3x3 operator * (Matrix3x3 *M);
    Vector3 operator * (Vector3 V);
    //Vector3 operator * (Vector3 *V);
    Matrix3x3 operator * (double R);
    //Matrix3x3 operator * (double *R);
    Matrix3x3 operator / (double R);
    //Matrix3x3 operator / (double *R);
    int operator == (Matrix3x3 M);
    //int operator == (Matrix3x3 *M);
    int operator != (Matrix3x3 M);
    //int operator != (Matrix3x3 *M);

    Matrix3x3 setRotationMatrix(Vector3 V, double R);
    friend Matrix3x3 makeRotationMatrix(Vector3 V, double R);
    double getMatrixDeterminant(Matrix3x3 M);

    friend class Vector3;
};
Matrix3x3 makeRotationMatrix(Vector3 V, double R);


#endif // MATRIX_H_INCLUDED
